#include <ctime>
#include <cstdlib>
#include <iostream>
#include "Student.h"
#include "School.h"

using namespace std;

void inline swap(int &x, int &y) {int t = x; x = y; y = t;}
void randomIt(int x[], int n) {
	for (int i=0; i<n; ++i)
		swap(x[rand()%n], x[rand()%n]);
}

int main(int argc, char* argv[])
{
	srand((unsigned int)time(0));

	//set schools
	const int m = 6;
	School schools[m];
	for (int i=0; i<m; ++i)
		schools[i].number = i;
	for (int i=0; i<4; ++i)
		schools[i].allowed = 3;
	for (int i=4; i<6; ++i)
		schools[i].allowed = 6;
	schools[0].synQuality = schools[1].synQuality = 1;
	schools[0].artQuality = 2;
	schools[0].sciQuality = 1;
	schools[1].artQuality = 1;
	schools[1].sciQuality = 2;

	//set students
	const int n = 24;
	Student students[n];
	int order[n];
	for (int i=0; i<n; ++i)
		order[i] = i;
	int schOrd[m];
	for (int i=0; i<m-2; ++i)
		schOrd[i] = i;

	//	randomIt(order, n);
	for (int i=0; i<n; ++i) {
		students[i].number = order[i];
		students[i].wish = new int[m];
		students[i].wishNum = m;
		randomIt(schOrd, m-2);
		if ((order[i] + 1)%2 == 0) {
			students[i].artQuality = 1;
			students[i].wish[0] = 0;
			students[i].wish[1] = 1;
			for (int j=0; j<m-2; ++j)
				students[i].wish[j+2] = schOrd[j] + 2;
		}
		else {
			students[i].sciQuality = 1;
			students[i].wish[0] = 1;
			students[i].wish[1] = 0;
			for (int j=0; j<m-2; ++j)
				students[i].wish[j+2] = schOrd[j] + 2;
		}
	}
	randomIt(order, n);
	for (int i=0; i<n; ++i)
		students[i].synQuality = rand() % 41 + 60;

	for (int i=0; i<n; ++i)
		students[i].showMe();
	cout << endl;
	for (int i=0; i<m; ++i)
		schools[i].showMe();
	cout << endl;

	//begin testing four....
	cout << "this is test 4" << endl;

	School bufSch;//here use for sorting
	for (int i=0; i<n; ++i)
		bufSch.received.push(students[i]);
	int totalQual = 0, count = 4;
	for (int i=0; i<count; ++i) {
		totalQual += bufSch.received.top().synQuality;
		bufSch.received.pop();
	}
	double avg1, avg2;
	avg1 = totalQual / count * 1.0;
	totalQual = 0;
	for (int i=0; i<n - count; ++i) {
		totalQual += bufSch.received.top().synQuality;
		bufSch.received.pop();
	}
	avg2 = totalQual / (n - count) * 1.0;

	for (int i=0; i<n; ++i) {
		if (students[i].synQuality > avg1)
			for (int j=0; j<2; ++j)
				schools[j].received.push(students[i]);
		if (students[i].synQuality > avg2)
			for (int j=2; j<m; ++j)
				schools[j].received.push(students[i]);
	}

	int left = n;
	bool mark[n];
	memset(mark, 0, n);

	//first wish
	for (int i=0; i<m; ++i) {
		while (schools[i].allowed > 0 && !schools[i].received.empty()) {
			Student stu = schools[i].received.top();
			schools[i].received.pop();
			if (mark[stu.number])
				continue;
			if (stu.wish[0] != i)
				continue;
			mark[stu.number] = true;
			students[stu.number].mySchool = &schools[i];
			--schools[i].allowed;
			--left;
		}
	}

	int k = 1;
	for (int i=0; i<m; ++i)
		while (!schools[i].received.empty())
			schools[i].received.pop();
	while (!bufSch.received.empty())
		bufSch.received.pop();

	while (left > 0 && k < m) {
		for (int i=0; i<n; ++i)
			if (!mark[i])
				schools[students[i].wish[k]].received.push(students[i]);

		int tmpAllowed;
		for (int i=0; i<m; ++i) {
			tmpAllowed = schools[i].allowed;
			while (schools[i].allowed > 0 && !schools[i].received.empty()) {
				Student& stu = schools[i].received.top();
				mark[stu.number] = true;
				--schools[i].allowed;
				schools[i].received.pop();
				students[stu.number].mySchool = &schools[i];
				--left;
				bufSch.received.push(stu);
			}
			while (!schools[i].received.empty()) {
				Student& stu = schools[i].received.top();
				mark[stu.number] = false;
				schools[i].received.pop();
				students[stu.number].mySchool = 0;
				++left;
			}
			while (!bufSch.received.empty()) {
				schools[i].received.push(bufSch.received.top());
				bufSch.received.pop();
			}
			schools[i].allowed = tmpAllowed;
		}
		++k;
	}
	cout << "match result:" << endl;
	cout << "student\t" << "school\t" << "score\t" << "money" << endl;
	for (int i=0; i<n; ++i)
		cout << students[i].number+1 << "\t" 
		<< (students[i].mySchool == 0 ? 'x' : char(students[i].mySchool->number+'A')) << "\t"
		<< students[i].calScore() << "\t" 
		<< students[i].calMoney() << endl;
	//end test four.

	system("pause");
	return 0;
}
